/************************************************************************************
 *  Title: tb.cpp (Calculator Project)
 *  Author: Anthony Schaefer, Umar Butt, Talha Ansari
 *  Date: 04/25/2010
 *  Description: Top level behavior for simple calculator project, SystemC version
 ************************************************************************************/


#include <systemc.h>
#include <iostream>
#include <iomanip>
using namespace std;


SC_MODULE (InputOutput)
{
	sc_fifo_in<float> dataOut;
	sc_fifo_out<float> firstData;
	sc_fifo_out<char> operatorData;
	sc_fifo_out<float> secondData;
	
	void IO()
	{
		float data1;
		char data2;
		float data3;
		float data4;
		
		while (1) {
			/* Get first data */
			cout << "Enter the first number: ";
			scanf("%f",&data1);
			getchar();
			
			/* Get operator */
			cout << "Enter operator (/, *, +, -): ";
			scanf("%c",&data2);
			getchar();
			
			/* Get second data */
			cout << "Enter the second number: ";
			scanf("%f",&data3);
			getchar();
			
			/* Send data over a fifo */
			firstData.write(data1);
			operatorData.write(data2);
			secondData.write(data3);
			
			/* Receive output data for display */
			data4 = dataOut.read();
			//printf("Answer is %f \n\n",c);
			cout << "Answer is = " << data4 << endl;
		}
	}
	
	
	SC_CTOR (InputOutput)
	{
		SC_THREAD (IO);
	}
};



SC_MODULE (Calc)
{
	sc_fifo_in<float> firstData;
	sc_fifo_in<char> operatorData;
	sc_fifo_in<float> secondData;
	sc_fifo_out<float> dataOut;
	
	void customCalc ()
	{
		float data1;
		char data2;
		float data3;
		float data4;
		
		while (1) {
			
			/* Read in all data for calculation */
			data1 = firstData.read();
			data2 = operatorData.read();
			data3 = secondData.read();
	
			/* Compute necessary calculations */
			if (data2 == '*')
			{
				data4 = data1 * data3;
			}
			
			if (data2 == '/')
			{
				data4 = data1 / data3;
			}
			
			if (data2 == '+')
			{
				data4 = data1 + data3;
			}
			
			if (data2 == '-')
			{
				data4 = data1 - data3;
			}
			
			/* Send calculated data out */			
			dataOut.write(data4);
		}
	}
	
	SC_CTOR (Calc)
	{
		SC_THREAD (customCalc);
	}
};



SC_MODULE (top)
{
	/* Define all fifos used in design */
	sc_fifo<float> *fifoFirstData;
	sc_fifo<char> *fifoOperatorData;
	sc_fifo<float> *fifoSecondData;
	sc_fifo<float> *fifoDataOut;
	
	/* Declare instances of modules */
	InputOutput *io_inst;
	Calc *calc_inst;
	
	SC_CTOR (top)
	{
		fifoFirstData = new sc_fifo<float>("FIFOFIRSTDATA");
		fifoOperatorData = new sc_fifo<char>("FIFOOPERATORDATA");
		fifoSecondData = new sc_fifo<float>("FIFOSECONDDATA");
		fifoDataOut = new sc_fifo<float>("FIFODATAOUT");
		
		io_inst = new InputOutput("INPUTOUTPUT");
		io_inst -> firstData(*fifoFirstData);
		io_inst -> operatorData(*fifoOperatorData);
		io_inst -> secondData(*fifoSecondData);
		io_inst -> dataOut(*fifoDataOut);
		
		calc_inst = new Calc("CALC");
		calc_inst -> firstData(*fifoFirstData);
		calc_inst -> operatorData(*fifoOperatorData);
		calc_inst -> secondData(*fifoSecondData);
		calc_inst -> dataOut(*fifoDataOut);
	}
};



int sc_main (int argc , char *argv[]) {
   top top1("Top1");
   sc_start();
   return 0;
}
